<?php
/**
 * alltosun.com  push.php
 * ============================================================================
 * 版权所有 (C) 2009-2013 北京互动阳光科技有限公司，并保留所有权利。
 * 网站地址: http://www.alltosun.com
 * ----------------------------------------------------------------------------
 * 许可声明：这是一个开源程序，未经许可不得将本软件的整体或任何部分用于商业用途及再发布。
 * ============================================================================
 * $Author: 王德康 (wangdk@alltosun.com) $
 * $Date: 2015-11-29 下午4:43:07 $
 * $Id: push.php 178586 2016-04-19 04:31:58Z wangdk $
 */

//require 'helper/AnHttp/AnCurl.php';
require 'helper/AnCurl.php';

class push_widget
{
    // 推送配置
    private $conf;

    private $type;

    private $err;

    public function __construct()
    {
        $this->conf = push_config::$conf;
    }

    /**
     * 推送消息
     * @param  array $msg          必填 要推送的消息内容
     * @param  array  $user_ids     可选 要推的用户id 不填默认为广播
     * @param  string    $type         可选  type=manage 经销商和市场人员app， type=store 终端app
     * @param  string    $tag_ids      可选  组ID
     * @return string|array         失败返回失败消息
     *
     */
    public function send($msg, $user_ids = array(), $type = "manage", $tag_ids = array())
    {
        $this->type = $type;

        $data = $this->format_data($msg, $user_ids, $tag_ids);
        if (!$data) {
            return $this->err;
        }

        $result = $this->exec_push($data);
        return $this->view_result($result);
    }

    /**
     * 执行请求
     * @param string $url    请求的url
     * @param string $type   请求类型 支持 get post
     * @param array  $data   传递的参数
     */
    private function curl_get($url, $data, $header)
    {
        $curlHandle = curl_init();
        // 设置url
        curl_setopt($curlHandle, CURLOPT_URL, $url);
        // 设置连接超时时间
        curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 10);

        // 设置header头
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $header);

        // 获取页面内容，不直接输出到页面
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);

        $result =  curl_exec($curlHandle);
        if (!$result) {
            return curl_error($curlHandle);
        }

        curl_close($curlHandle);
        return $result;
    }

    /**
     * 执行请求
     * @param string $url    请求的url
     * @param string $type   请求类型 支持 get post
     * @param array  $data   传递的参数
     */
    private function curl_post($url, $data, $header)
    {
        $curlHandle = curl_init();
        // 设置url
        curl_setopt($curlHandle, CURLOPT_URL, $url);
        // 设置连接超时时间
        curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 10);

        // 设置header头
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $header);

        // 获取页面内容，不直接输出到页面
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);

        curl_setopt($curlHandle, CURLOPT_POST, 1);

        curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $data);

        curl_setopt($curlHandle,  CURLOPT_FOLLOWLOCATION, 1);


        $result =  curl_exec($curlHandle);
        if (!$result) {
            return curl_error($curlHandle);
        }

        curl_close($curlHandle);
        return $result;
    }

    /**
     * 执行推送
     * @param unknown $data
     * @param int $type
     * @return mixed
     */
    private function exec_push($data)
    {
        // 请求的接口
        $url = $this->conf['interface'];

        // 需要的header头信息
        $header = $this->get_header($this->type);

        // 发送通知
        $result = $this->curl_post($url, $data, $header['header']);

        return json_decode($result, true);
    }

    /**
     * 推送结果展示方法 处理错误信息 错误号之类
     */
    private function view_result($result)
    {
        if (isset($result['error'])) {
            $http_status_code = push_config::$http_status_code;
            return $http_status_code[$result['error']['code']];
        }
        return array('info'=>'ok');
    }


    /**
     * 处理数据 返回拼装好的json数据
     * @param array $msg
     * @param unknown $user_ids
     * @return string
     */
    public function format_data($msg, $user_ids = array(), $tag_ids = array())
    {
        // 初始化推送数组
        $init_infos = push_config::$init_infos;

        if ($user_ids) {

            // 获取所有用户的设备ID
            $reg_ids = push_helper::get_device_ids($user_ids);
            if (!$reg_ids) {
                $this->err = 'not found device id';
                return false;
            }

            $init_infos['audience'] = array();
            $init_infos['audience']['registration_id'] = $reg_ids;

        } else if ($tag_ids) {
            // 标签
            $tag_names = _model('push_group')->getFields('name', array('id'=>$tag_ids));
            $init_infos['audience']['tag'] = $tag_names;
        }

        if (is_array($msg)) {
            foreach ($msg as $k => $v) {
                if ($k == 'content') {
                    $init_infos['notification']['alert'] = $v;
                } else {
                    // 附加字段，比如：跳转的地址
                    $init_infos['notification']['android']['extras'][$k] = $v;
                    $init_infos['notification']['ios']['extras'][$k]     = $v;
                }
            }
        } else {
            $init_infos['notification']['alert'] = $msg;
        }

        // 生产环境
        if (!ONDEV) {
            $init_infos['options']['apns_production'] = true;
        }

        return json_encode($init_infos);
    }

    /**
     * 获取请求头信息
     * @return multitype:multitype:string
     */
    private function get_header($type)
    {
        $appkey         = $type.'_appkey';
        $master_secret  = $type.'_master_secret';

        $header = array(
                'Content-Type: application/json',
                'Authorization: Basic '.base64_encode($this->conf[$appkey].':'.$this->conf[$master_secret])
        );
        return array('header'=>$header);
    }


    /**
     * 检测用户登录异常，当前登录用户设备ID和之前注册的设备ID是否一样
     * @param unknown $user_id
     * @param unknown $reg_id
     */
    public function check_exception($user_id, $reg_id)
    {
        $result = $this->check_account_exception($user_id, $reg_id);
        // 异常返回的是0
        if (!$result) {

            // 推送并保存记录在另一张表
            // $content = '您的账号已在其他设备登陆，非本人操作请及时修改密码。';
            $content = sprintf('您的账号于[%s]在其他设备登录', date('Y-m-d H:i:s'));

            $this->send(array('content'=>$content, 'res_name'=>'single_login'), array($user_id));

            _model('account_exception')->create(array(
                'user_id'    => $user_id,
                'reg_id'     => _uri('device', array('user_id'=>$user_id), 'reg_id'),
                'related_id' => $reg_id,
                'content'    => $content,
                'add_time'   => date('Y-m-d H:i:s')
            ));
        }
    }

    /**
     * 检测用户在当前设备是否允许登录
     * 检测场景：
     * 1. 用户打开应用的时候
     * 2. 用户登录成功后
     * @param unknown $user_id
     * @param unknown $reg_id
     * @return string|multitype:string
     */
    private function check_account_exception($user_id, $reg_id)
    {
        if (!$user_id) {
            return false;
        }

        $logged_reg_id = _uri('device', array('user_id'=>$user_id), 'reg_id');

        if ($logged_reg_id && $reg_id != $logged_reg_id) {
            return true;
        }
        return false;
    }

    /**
     * 查询设备下分组
     * @param int $reg_id        极光下的设备id
     * @param int $tag_id        本站存储的标签id
     * @param string $res_name   对标签的操作名称, add/remove
     */
    public function get_device_tags($reg_id,$type = 'manage')
    {
        $this->type = $type;
        $url = 'https://device.jpush.cn/v3/devices/'.$reg_id;

        $header = $this->get_header($this->type);
        $result = $this->curl_get($url, '', $header['header']);

        return $result;
    }

    /**
     * 更新设备下的标签
     * @param int $reg_id        极光下的设备id
     * @param int $tag_id        本站存储的标签id
     * @param string $res_name   对标签的操作名称, add/remove
     */
    public function update_device_tags($reg_id, $res_name, $tag, $type = 'manage')
    {
        $this->type = $type;
        $url = 'https://device.jpush.cn/v3/devices/'.$reg_id;

        $params = array(
                'tags' => array(
                        $res_name => array($tag)
                )
        );

        $params = json_encode($params);
        $header = $this->get_header($this->type);

        $result = $this->curl_post($url, $params, $header['header']);

        // 正常情况下是没有返回消息的
        return $result;
    }
}
?>